package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/binary"
	"log"
	"time"
)

//定义结构
type Block struct {
	//版本号
	Version uint64
	//Merkel根
	MerkelRoot []byte
	//时间戳
	TimeStamp uint64
	//难度值
	Difficulty uint64
	//随机数, 也就是挖矿找的数据
	Nonce uint64
	//前区块哈希
	prevHash []byte
	//当前区块哈希
	Hash []byte
	//数据
	Data []byte
}

//实现一个辅助函数, 将uint64转成[]byte
func Unit64ToByte(num uint64) []byte {
	var buffer bytes.Buffer
	err := binary.Write(&buffer, binary.BigEndian, num)
	if err != nil {
		log.Panic(err)
	}
	return buffer.Bytes()
}

//创建区块
func NewBlock(data string, prevBlockHash []byte) *Block {
	block := Block{
		Version:    00,
		prevHash:   prevBlockHash,
		MerkelRoot: []byte{},
		TimeStamp:  uint64(time.Now().Unix()),
		Difficulty: 0, //随便填写的无效值
		Nonce:      0,
		Hash:       []byte{}, //后期进行计算
		Data:       []byte(data),
	}
	block.SetHash()
	return &block
}

//生成哈希
func (block *Block) SetHash() {
	//var blockInfo []byte
	//拼装数据
	//blockInfo = append(blockInfo, Unit64ToByte(block.Version)...)
	//blockInfo = append(blockInfo, block.prevHash...)
	//blockInfo = append(blockInfo, block.MerkelRoot...)
	//blockInfo = append(blockInfo, Unit64ToByte(block.TimeStamp)...)
	//blockInfo = append(blockInfo, Unit64ToByte(block.Difficulty)...)
	//blockInfo = append(blockInfo, Unit64ToByte(block.Nonce)...)
	//blockInfo = append(blockInfo, block.Data...)

	//使用join来优化数据
	tmp := [][]byte{
		Unit64ToByte(block.Version),
		block.prevHash,
		block.MerkelRoot,
		Unit64ToByte(block.TimeStamp),
		Unit64ToByte(block.Difficulty),
		block.Data,
	}
	//将二维的切片数组连接起来, 返回一个一维的切片
	blockInfo := bytes.Join(tmp, []byte{})
	//sha256
	hash := sha256.Sum256(blockInfo)
	block.Hash = hash[:]
}

//引入区块链
type BlockChain struct {
	//定义一个区块链数组
	blocks []*Block
}
